package com.echo.register.commons.redis;

import com.alibaba.fastjson.JSON;
import com.echo.register.commons.Constants;
import com.echo.register.commons.utils.SerializeUtil;
import com.echo.register.domain.VoteCadidate;
import com.echo.register.mapper.CadidateMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.annotation.Resource;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @program: com.echo.voter
 * @description: Redis客户端
 * @author: Xiaoti
 * @create: 2018-11-02 17:25
 **/
@Component
public class RedisClient implements InitializingBean {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private JedisPool jedisPool = new JedisPool();

    @Resource
    private RedisConfig redisConfig;

    @Resource
    private CadidateMapper cadidateMapper;

    private Jedis getResource(){
        return jedisPool.getResource();
    }

    public void returnResource(Jedis jedis, Boolean b){
        if(b){
            jedisPool.returnBrokenResource(jedis);
        }else {
            jedisPool.returnResource(jedis);
        }
    }

    /**
     * 判断是否存在
     * @param key
     * @return
     */
    public boolean exists(String key){
        boolean broken = false;
        Jedis jedis = this.getResource();
        boolean result = false;
        try{
            result = jedis.exists(key);
            logger.info("Success exec command [exists].key : {}, result: {}", key, result);
        }catch (Exception e){
            broken = true;
            logger.error(e.getMessage(), e);
        }finally {
            this.returnResource(jedis, broken);
        }
        return result;
    }

    /**
     * 从redis中获取对象
     * @param t
     * @param key
     * @param <T>
     * @return
     */
    public <T>T getObject(Class<T> t, String key){
        String json = this.getString(key);
        return JSON.parseObject(json, t);
    }

    /**
     * 从redis中获取字符串
     * @param key
     * @return
     */
    public String getString(String key){
        boolean broken = false;
        Jedis jedis = this.getResource();
        String result = null;
        try{
            result = jedis.get(key);
            logger.info("Success exec command [get]. key: {}, result: {}", key, result);
        }catch (Exception e){
        broken = true;
        logger.error(e.getMessage(), e);
        }finally {
            this.returnResource(jedis, broken);
        }
        return result;
    }

    /**
     * 设置对象到Redis，序列化成Json字符串保存
     * @param key
     * @param obj
     * @param seconds
     */
    public void setexObjec(String key, Object obj, int seconds){
        String json = JSON.toJSONString(obj);
        this.setexString(key, json, seconds);
    }

    /**
     * 设置字符串到Redis中
     * @param key
     * @param str
     * @param seconds
     */
    public void setexString(String key, String str, int seconds){
        boolean broken = false;
        Jedis jedis = this.getResource();
        try{
            jedis.setex(key, seconds, str);
            logger.info("Success exec command [setex]. key: {}, seconds: {}", key, str, seconds);
        }catch (Exception e){
            broken = true;
            logger.error(e.getMessage(), e);
        }finally {
            this.returnResource(jedis, broken);
        }
    }

    /**
     * 续期
     * @param key
     * @param seconds
     */
    public void expire(String key, int seconds){
        boolean broken = false;
        Jedis jedis = this.getResource();
        try{
            jedis.expire(key, seconds);
            logger.info("Success exec command [expire]. key: {}, seconds: {}", key, seconds);
        }catch (Exception e){
            broken = true;
            logger.error(e.getMessage(), e);
        }finally {
            this.returnResource(jedis, broken);
        }
    }

    public void del(String key){
        boolean broken = false;
        Jedis jedis = this.getResource();
        Long result = null;
        try{
            result = jedis.del(key);
            logger.info("Success exec command [del]. key: {}, del lines: {}", key, result);
        }catch (Exception e){
            broken = true;
            logger.error(e.getMessage(), e);
        }finally {
            this.returnResource(jedis, broken);
        }
    }

    public Set<String> keys(String pattern){
        boolean broken = false;
        Jedis jedis = this.getResource();
        Set<String> result = null;
        try{
            result = jedis.keys(pattern);
            logger.info("Success exec command [keys]. pattern: {}, result: {}", pattern, result);
        }catch (Exception e){
            broken = true;
            logger.error(e.getMessage(), e);
        }finally {
            this.returnResource(jedis, broken);
        }
        return result;
    }

    /**
     * 设置List集合
     * @param key
     * @param list
     */
    public void setList(String key ,List<?> list, int seconds){
        Jedis jedis = jedisPool.getResource();
        try {
            if(list == null || list.size() == 0){
                jedis.setex(key.getBytes(), seconds, "".getBytes());
            }else{//如果list为空,则设置一个空
                jedis.setex(key.getBytes(), seconds, SerializeUtil.serializeList(list));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jedis.close();
        }
    }

    /**
     * 获取List集合
     * @param key
     * @return
     */
    public List<?> getList(String key){
        Jedis jedis = jedisPool.getResource();
        if (jedis == null || !jedis.exists(key)) {
            return null;
        }
        byte[] data = jedis.get(key.getBytes());
        jedis.close();
        return SerializeUtil.unserializeList(data);
    }

    @Override
    public void afterPropertiesSet() throws Exception{
        String strUri = redisConfig.getRedisServersURI();
        URI uri = new URI(strUri);
        String host = uri.getHost();
        int port = uri.getPort();
        String pwd = uri.getUserInfo().split(":", 2)[1];
        jedisPool = new JedisPool(redisConfig.getJedisConfig(), host, port, redisConfig.getTimeout() * 1000, pwd);
        logger.info("Init JedisPool , host: {}, prot: {}, pwd: {}", host, port, pwd);

        this.exists("test");
        logger.info("实例化Redis连接池，并测试成功");

        //初始化参选人数据
        initCadidates(Constants.CadidateGroup.AQWS);
        initCadidates(Constants.CadidateGroup.FWMY);
        initCadidates(Constants.CadidateGroup.KJCX);
        initCadidates(Constants.CadidateGroup.KJXR);
        initCadidates(Constants.CadidateGroup.SJXF);
        initCadidates(Constants.CadidateGroup.ZYYY);
    }

    public void initCadidates(String cadidateGroup){
        List<VoteCadidate> cadidates = cadidateMapper.getCadidateList(cadidateGroup);
        List<String> keys = new ArrayList<>();
        for (VoteCadidate cadidate : cadidates) {
            this.setexObjec(cadidate.getCadidateId(), cadidate, CadidateKey.TOKEN_EXPIRE);
            keys.add(cadidate.getCadidateId());
        }
        this.setList(cadidateGroup, keys, CadidateKey.TOKEN_EXPIRE);
    }
}
